﻿using System;
using Super_Management_Mayhem.Content.Spritesheet;
using Super_Management_Mayhem.Screens.Playing.ObjectInterfaces;
using Super_Management_Mayhem.Screens.Playing.Players;
using Transformable_Engine_v2.Engine.Animation.PositionAnimation;
using Transformable_Engine_v2.Engine.Animation.ScaleAnimation;
using Transformable_Engine_v2.Engine.Animation.Trajectory;
using Transformable_Engine_v2.Engine.GameObjects.Containers;
using Transformable_Engine_v2.Engine.GameObjects.Primitives;
using Transformable_Engine_v2.Engine.Graphics;
using Transformable_Engine_v2.Engine.Helper;
using Transformable_Engine_v2.Engine.Time;
using Transformable_Engine_v2.Engine.Transformable_Math.Geometry;

namespace Super_Management_Mayhem.Screens.Playing.Points
{
    public class Point : PositionTrackerContainer, ICollectible
    {
        private TE_Rectangle _boundingBoxCollect;
        private PositionUniformLinearAnimation _positionAnimation;
        private Timer _tossTimer;

        private bool _isMoving;

        public enum PointType
        {
            One = 1,
            Three = 3,
            Five = 5,
            Ten = 10,
        }

        private int _value;

        public Point(TE_Vector2 position, PointType value, TE_Vector2 tossDirection, int duration, TE_Rectangle hole)
        {
            Initialize(position, value, duration, true);

            var direction = tossDirection.ToUnit();
            var furthestDirection = hole.GetFurthestInDirection(position, direction);
            AddAnimations(new PositionAnimation(new QuadraticEasing(BaseTrajectory.Easing.EaseOut), 
                                                (Position + furthestDirection + (direction * Randomizer.Double(0.5f, 3)).ToGridbound()).AsGridBound(),
                                                duration * Randomizer.Double(0.8, 1.5), false, 0));
        }

        public Point(TE_Vector2 position, PointType value, TE_Vector2 tossDirection, int duration)
        {
            Initialize(position, value, duration, false);

            _positionAnimation = new PositionUniformLinearAnimation(0, tossDirection, -tossDirection * (1000.0 / duration));
            AddAnimations(_positionAnimation);
        }

        void Initialize(TE_Vector2 position, PointType value, int duration, bool scale)
        {
            Position = position;

            ImageContainer item = new ImageContainer();

            _boundingBoxCollect = new TE_Rectangle(0, 0, 0.5f, 0.5f, TE_Rectangle.Alignment.CenterMiddle).ToGridBound();

            _value = (int) value;
            switch (value)
            {
                case PointType.One:
                    item.Sprite = PointSheet.GetSprite(PointSheet.Point.One);
                    item.Scale = new TE_Vector2(0.75f, 0.75f);
                    break;
                case PointType.Three:
                    item.Sprite = PointSheet.GetSprite(PointSheet.Point.Three);
                    break;
                case PointType.Five:
                    item.Sprite = PointSheet.GetSprite(PointSheet.Point.Five);
                    break;
                case PointType.Ten:
                    item.Sprite = PointSheet.GetSprite(PointSheet.Point.Ten);
                    item.Scale = new TE_Vector2(0.5f, 0.5f);
                    break;
            }

            if(scale)
            {
                var finalScale = item.Scale;

                item.Scale = TE_Vector2.Zero;
                item.AddAnimations(new ScaleAnimation(new OvershootEasing(BaseTrajectory.Easing.EaseOut, 3), finalScale, duration, false, 0));
            }

            item.Origin = TE_Rectangle.Alignment.CenterMiddle;

            item.AddAnimations(new PositionAnimation(new SinusTrajectory(1), new TE_Vector2(0, -0.125f), 1000, true, Randomizer.Int(0, 500)));

            AddChildren(item);

            _tossTimer = new Timer(duration, false, EndToss);
            _tossTimer.Start();
            AddTimers(_tossTimer);

            _isMoving = true;
        }

        public override void FixedStepUpdate(TimeSpan gameTime)
        {
            if (_isMoving)
            {
                TE_Vector2 normal;
                var collisionOffset = Playscreen.Map.ResolveCollision(_boundingBoxCollect + OldPosition,
                                                                      _boundingBoxCollect + Position, Position - OldPosition, out normal);
                if (collisionOffset != null)
                {
                    
                    if (_positionAnimation != null && normal.X != 0)
                        _positionAnimation.FlipHorizontal();
                    if (_positionAnimation != null && normal.Y != 0)
                        _positionAnimation.FlipVertical();
                    
                    Position = collisionOffset - _boundingBoxCollect.Position;
                    Position = collisionOffset - _boundingBoxCollect.Position;
                }
            }
            base.FixedStepUpdate(gameTime);
        }

        private void EndToss()
        {
            ClearAnimation<PositionUniformLinearAnimation>();
            _isMoving = false;
        }

        public float GetOrderingFactor()
        {
            return Position.Y;
        }

        public TE_Rectangle GetBoundingBoxCollect()
        {
            if(IsAlive())
                return _boundingBoxCollect + Position;

            return TE_Rectangle.Zero;
        }

        public void Collect(PlayerContainer collector)
        {
            collector.CollectPoint(_value);
            Die();
        }
    }
}